package cn.pku.edu.cs.ldn.thread;

import android.os.Bundle;
import android.os.Handler;
import android.os.Message;

public abstract class ThreadObserverHandler extends Handler {

	public static final String KEY_PROCESSED = "processed";
	public static final String KEY_TOTAL = "total";
	public static final String KEY_FINISH = "finish";
	public static final String KEY_START = "start";
	public static final String KEY_RESULT = "result";
	public static final String KEY_STOP = "stop";

	private Object resultObject = null;

	/**
	 * runs on UI thread
	 */
	public abstract void preRun();

	/**
	 * runs on UI thread
	 * 
	 * @param process
	 * @param total
	 */
	public abstract void inRun(float processed, float total);

	/**
	 * runs on UI thread
	 */
	public abstract void postRun(Object object);

	/**
	 * runs on UI thread
	 */
	public abstract void onStop();

	@Override
	public void handleMessage(Message msg) {
		Bundle bundle = msg.getData();
		if (bundle == null) {
			// TODO
		} else {
			boolean start = bundle.getBoolean(KEY_START, false);
			if (start) {
				preRun();
				return;
			}
			boolean stop = bundle.getBoolean(KEY_STOP, false);
			if (stop) {
				onStop();
				return;
			}
			boolean finish = bundle.getBoolean(KEY_FINISH, false);
			if (finish) {
				postRun(resultObject);
				return;
			}
			float processed = bundle.getFloat(KEY_PROCESSED, 0f);
			float total = bundle.getFloat(KEY_TOTAL, 0f);
			inRun(processed, total);
		}
	}

	public void notifyProgress(float progressed, float total) {
		Message msg = obtainMessage();
		Bundle bundle = new Bundle();
		bundle.putFloat(KEY_PROCESSED, progressed);
		bundle.putFloat(KEY_TOTAL, total);
		msg.setData(bundle);
		sendMessage(msg);
	}

	public void notifyFinish(Object object) {
		Message msg = obtainMessage();
		Bundle bundle = new Bundle();
		bundle.putBoolean(KEY_FINISH, true);
		resultObject = object;
		msg.setData(bundle);
		sendMessage(msg);
	}

	public void notifyStart() {
		Message msg = obtainMessage();
		Bundle bundle = new Bundle();
		bundle.putBoolean(KEY_START, true);
		msg.setData(bundle);
		sendMessage(msg);
	}

	public void notifyStop() {
		Message msg = obtainMessage();
		Bundle bundle = new Bundle();
		bundle.putBoolean(KEY_STOP, true);
		msg.setData(bundle);
		sendMessage(msg);
	}
}
